Quiero construir un gráfico de anillos svg simple, con etiquetas y polilíneas que conecten los sectores con el texto de la etiqueta como este.
Sé que esto es posible usando d3.js como se implementó aquí, pero estoy restringido a usar un gráfico simple sin bibliotecas.
Este es el código que tengo ahora;
<div class="wrapper"> <svg viewBox="0 0 42 42" preserveAspectRatio="xMidYMid meet" class="donut"> <circle class="donut-hole" cx="21" cy="21" r="15.91549430918954" fill="#fff"></circle> <circle class="donut-ring" cx="21" cy="21" r="15.91549430918954" fill="transparent" stroke="#d2d3d4" stroke-width="3"></circle> <circle class="donut-segment" data-per="20" cx="21" cy="21" r="15.91549430918954" fill="transparent" stroke="#49A0CC" stroke-width="3" stroke-dasharray="50 50" stroke-dashoffset="25"></circle> <circle class="donut-segment" data-per="30" cx="21" cy="21" r="15.91549430918954" fill="transparent" stroke="#254C66" stroke-width="3" stroke-dasharray="50 50" stroke-dashoffset="75"></circle> <!-- stroke-dashoffset formula: 100 − All preceding segments' total length + First segment's offset = Current segment offset --> </svg> </div>
¿Algún consejo sobre cómo dibujar polilíneas y colocarlas correctamente sin superposición?
EDITAR: Quiero ingresar datos dinámicos al componente para que dibuje el gráfico cada vez que se cambien los datos.
implementaciones en d3: impl1
Mi principal duda era calcular los puntos de los arcos que hay que dibujar para un gráfico de anillos, que luego entendí gracias a esta genial respuesta de enxaneta .
Todo lo que tenía que resolver era agregar el tercer punto para la polilínea, si el texto.xCoordinate estaba más cerca de cualquier lado del svg, lo movía hacia la izquierda o hacia la derecha en una cantidad preestablecida. También tuve que dividir las etiquetas en múltiples <tspan>
s ya que los elementos <text>
no romperían el texto largo y el SVG recortaría las etiquetas largas. También es posible agregar HTML dentro de un <foreignObject>
y colocarlo correctamente para superar el problema de ajuste de texto.
Otra opción es usar elementos <path>
para generar arcos, pero no estoy seguro de cómo calcular el centroide de cada uno de los arcos.
Lectura recomendada:
<circle>
gráfico de anillos algo así como la respuesta de enxaneta, con los atributos explicados.<circle>
<path>
gráfico de anillos como se mencionó anteriormente, implementado maravillosamente por Mustapha.